package olegroshka.src.com.bofa.olegroshka.datasource;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

import olegroshka.src.com.bofa.olegroshka.sort.SortCriteria;
import olegroshka.src.com.bofa.olegroshka.sort.SortOrder;


public class SortingDataSource implements DataSource<Object[]> {

	private final SortCriteria[] sortCriterias; 
	private final DataSource<Object[]> dataSource; 
	
	public SortingDataSource(
			DataSource<Object[]> dataSource,
			SortCriteria[] sortCriterias) {
		this.dataSource = dataSource;
		this.sortCriterias = sortCriterias;
	}

	public Iterator<Object[]> iterator() {
		ArrayList<Object[]> list = new ArrayList<Object[]>();
		Iterator<Object[]> iterator = dataSource.iterator();
		while (iterator.hasNext()) {
			Object[] record = (Object[]) iterator.next();
			list.add(record);
		}
		Collections.sort(list, new Comparator<Object[]>() {
			@SuppressWarnings({ "rawtypes", "unchecked" })
			public int compare(Object[] leftRecord, Object[] rightRecord) {
				int c = 0;
				for (int i = 0; c == 0 && i < sortCriterias.length; i++) {
					SortCriteria sortCriteria = sortCriterias[i];
					int columnIndex = sortCriteria.getColumn();
					SortOrder sortOrder = sortCriteria.getOrder();
					if (leftRecord[i] instanceof Comparable) {
						Comparable lo = (Comparable) leftRecord[columnIndex];
						Comparable ro = (Comparable) rightRecord[columnIndex];
						c = sortOrder == SortOrder.ASC ? 
								lo.compareTo(ro) : ro.compareTo(lo);
					} else {
						throw new AssertionError("Record elements matching sort criteria "
										+ "must implement: " + Comparable.class.getName());
					}
				}
				return c;
			}
		});
		return list.iterator();
	}

	public void begin() {
		dataSource.begin();
	}

	public void end() {
		dataSource.end();
	}

}
